package com.yunkazaixian.syntelecom.utils;

import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 */
@Component
public class RedisUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // ===================== common ======================
    /**
     * 指定缓存失效时间
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取过期时间
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     */
    public boolean exists(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     */
    public void delete(String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }

    // ===================== string ======================
    /**
     * 写入缓存（永久有效）
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 写入缓存（带有效期，秒）
     */
    public boolean set(String key, Object value, Long expireTime) {
        try {
            if (expireTime > 0) {
                redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 写入缓存（带有效期和时间单位）
     */
    public boolean set(String key, Object value, Long expireTime, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForValue().set(key, value, expireTime, timeUnit);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 读取缓存
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        return (T) redisTemplate.opsForValue().get(key);
    }

    // ===================== hash ======================
    /**
     * 哈希表添加字段
     */
    public void hmSet(String key, Object hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 哈希表删除字段
     */
    public void hmDelete(String key, Object hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    /**
     * 哈希表获取字段值
     */
    public Object hmGet(String key, Object hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 获取哈希表大小
     */
    public Long getHashSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    // ===================== list ======================
    /**
     * 列表左侧添加元素
     */
    public void lPush(String k, Object v) {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        list.leftPush(k, v);
    }

    /**
     * 列表右侧弹出元素（带超时）
     */
    public Object getRightPop(String k, Long t) {
        return redisTemplate.opsForList().rightPop(k, t, TimeUnit.SECONDS);
    }

    /**
     * 获取列表长度
     */
    public Long getListSize(String k) {
        return redisTemplate.opsForList().size(k);
    }

    // ===================== set ======================
    /**
     * 集合添加元素
     */
    public void add(String key, Object value) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        set.add(key, value);
    }

    /**
     * 获取集合所有元素
     */
    public Set<Object> setMembers(String key) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        return set.members(key);
    }

    // ===================== zset ======================
    /**
     * 有序集合添加元素
     */
    public void zAdd(String key, Object value, double score) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        zset.add(key, value, score);
    }

    /**
     * 获取有序集合指定分数范围元素
     */
    public Set<Object> rangeByScore(String key, double minScore, double maxScore) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        return zset.rangeByScore(key, minScore, maxScore);
    }

    // ===================== 原子操作 ======================
    /**
     * 递增（自动创建键，初始值为1）
     */
    public long incrAndCreate(String key) {
        if (!exists(key)) {
            set(key, 1);
            return 1;
        }
        return incr(key, 1L);
    }

    /**
     * 递增（指定增量）
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    // ===================== 自定义方法（适配业务需求） ======================
    /**
     * 原子性设置键值对（仅当键不存在时设置）
     */
    public boolean setIfAbsent(String key, Object value, long expireTime, TimeUnit timeUnit) {
        try {
            // 直接使用带过期时间的原子操作
            return redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }



    // 在 RedisUtil 类中添加以下方法
    public Long lRem(String key, long count, Object value) {
        try {
            return redisTemplate.opsForList().remove(key, count, value);
        } catch (Exception e) {
            e.printStackTrace();
            return 0L;
        }
    }
    /**
     * 删除单个键
     * @param key 键
     */
    public void del(String key) {
        if (key != null) {
            redisTemplate.delete(key);
        }
    }

    /**
     * 删除多个键
     * @param keys 键集合
     */
    public void del(Collection<String> keys) {
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }


    /**
     * 向列表左侧添加多个元素
     */
    public void lPush(String key, Object... values) {
        redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 获取列表长度
     */
    public Long lSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 获取列表指定范围的元素
     */
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 修剪列表，保留指定范围的元素
     */
    public void lTrim(String key, long start, long end) {
        redisTemplate.opsForList().trim(key, start, end);
    }
}